Repository navigation
perf: stop old core-js from slowing down regex on every Vue 2 page, and repair 1.x CI - #347
Merged
Merged
Conversation
…ace on the whole page core-js 3.0 runs a feature check for String#split that writes `constructor` on a real RegExp. In V8 that write turns off the RegExp species protector for the whole page, so every String#split, #match, #replace and #search with a RegExp takes the slow path from then on, also in Vue's template compiler and in other libraries on the page. In Chromium 133, after nodeps.js loads, split(/\r?\n/g) on 729 KB goes from 0.5 ms to 41 ms, and global match/replace get 4-6x slower. core-js 3.3.4 changed this check to use a plain object (zloirock/core-js#306). Babel still injects the same core-js modules (the babel config does not change), so the browser support stays the same. nodeps.js grows by about 10 KB, which is just over webpack's 244 KiB size hint, so webpack now prints size warnings. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The build job installed ipyvue without a version, so it now gets ipyvue 3.0.0. With it, `python -m ipyvuetify.components` fails with KeyError: TraitNotAvailable in reacton's generator, and the build job fails before any test runs. The package itself already requires "ipyvue>=1.7,<2"; the build job now uses the same range. With the pin, the step exits 0 and components.py does not change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The release jobs published every tag with the npm dist-tag "latest". npm's latest for jupyter-vuetify is 3.0.0, so a 1.x patch release would move it back to 1.x, and `npm install jupyter-vuetify` and unpkg URLs without a version would get the old major. Releases from this branch now use the dist-tag "latest-1". npm rejects tags that look like a semver range, such as "1.x". The pre-release switch is gone: it read an input that only release events set, and release events do not trigger this workflow. core-js before 3.3.5 runs feature checks that write `constructor` on a real RegExp. In Chrome and Edge that turns off V8's fast paths for String#split, #match, #replace and #search on the whole page. jupyter-vuetify 1.11.3 shipped core-js 3.0.1 this way. A lockfile change or a new dependency can bring an old core-js back without anyone noticing, so the build job now scans every shipped bundle (nbextension, labextension, js/dist) for the core-js version marker and fails below 3.3.5. The script uses only the standard library, so the build job needs no extra install. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The build backend installs "jupyterlab~=4.0", so CI gets the newest 4.x. Since jupyterlab 4.6.0, `jupyter labextension build` goes through jupyter-builder, which stops on Node.js older than 20.19.0. The build job used Node 16, so the labextension build failed and webpack never wrote the nbextension. The sdist then had no built JS, and building the wheel from it failed with "No module named 'generate_source'", because the sdist does not ship the generator. The same failure happens on 1.x without this branch. The Node 16 pin worked around an OpenSSL error in webpack 4. The 1.x line has built with webpack 5 since early 2025, and webpack 5 runs on Node 22. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
maartenbreddels
force-pushed
the
perf/corejs-1x
branch
from
October 4, 2026 12:43
2f6dc96 to
251525a
Compare
maartenbreddels
marked this pull request as ready for review
October 5, 2026 08:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On the 1.x line, update core-js from 3.0.1 to 3.50.0. After this change, loading jupyter-vuetify no longer makes every regex
split,matchandreplaceon the page up to 80 times slower in Chrome and Edge. This PR also repairs CI on 1.x.Problem
Every page that loads jupyter-vuetify 1.x in Chrome or Edge gets slow regex work everywhere, not only in jupyter-vuetify.
Vue 2 apps (Solara with Vue 2, Voila and notebooks with ipyvuetify 1.x) pay for this on every page load.
The cause is core-js 3.0.1 in the bundles.
Its feature check for
String#splitwritesconstructoron a real RegExp.In V8, that write turns off the RegExp fast path for the whole page.
After that,
String#split,#match,#replaceand#searchwith a RegExp take the slow path, also in Vue's template compiler and in other libraries.In Chromium 133, after jupyter-vuetify 1.11.3's
nodeps.jsloads,split(/\r?\n/g)on a 729 KB string takes 41 ms instead of 0.5 ms.Global
matchandreplaceget 4 to 7 times slower.core-js fixed this check in 3.3.4 (zloirock/core-js#306): it now uses a plain object.
jupyter-vue 1.12.0 has the same problem (core-js 3.1.4), so both packages need the fix.
CI on the 1.x branch is broken: the build job installs ipyvue without a version and gets ipyvue 3.0.0.
With it,
python -m ipyvuetify.componentsfails withKeyError: TraitNotAvailablein reacton's generator.The build job also runs on Node 16.
The build backend installs the newest jupyterlab 4.x, and since jupyterlab 4.6.0 the labextension build stops on Node older than 20.19.0.
Then
python -m buildfails withNo module named 'generate_source', but that error is only a result of the first one: without the labextension build, webpack never writes the nbextension, and the sdist does not ship the generator that would rebuild it.Change
js/package.jsonandjs/package-lock.json: core-js 3.0.1 to 3.50.0 (^3.50.0).The babel config does not change, so babel injects the same polyfill modules and the browser support stays the same.
npm keeps a nested core-js 3.0.1 under the dev dependency
core-js-compat. It runs only at build time, and the scan below shows that no bundle ships it.nodeps.jsgrows by 3.3 KB gzip (50.4 to 53.8 KB)."ipyvue>=1.7,<2", the same range that the package requires.^20.19.0 || >=22.12.0.The release jobs only run
npm publishand keep Node 14.latest-1, notlatest.npm's
latestfor jupyter-vuetify is 3.0.0, and a 1.x release withlatestwould move it back to 1.x.npm rejects a tag such as
1.x, because it looks like a semver range.The old pre-release switch is removed: it read a release-event field, and this workflow never runs on release events.
prefix/share/jupyter/nbextensions,prefix/share/jupyter/labextensions/.../static,js/dist) for the core-js version marker.It fails when it finds a version below 3.3.5, so an old core-js cannot come back through a lockfile change.
The script
.github/check_corejs.pyuses only the Python standard library, so the build job needs no extra install.Validation
A page-load harness measured a large production Vue 2 Solara app, with synthetic data (solara 1.63.1, ipyvue 1.12.0, ipyvuetify 1.11.3).
It compared stock with the same core-js bump in both ipyvue and ipyvuetify.
The jupyter-vuetify
nodeps.jsin that test has the same sha256 (e8d0627b...) as the build of this branch.The metric is the time to the first useful view, cold cache, p50 of 20 loads per cell:
In the same loads, a 700 KB
split(/\r?\n/g)after the load took 35 ms (1x) and 152 ms (4x) with stock, and 0.3 ms and 1.1 ms with the fix.The DOM was the same, and no arm had console errors.
With only ipyvue fixed, the page stays slow. In a test page with 182 large templates (Playwright Chromium 133, 1x CPU), the split still took 42 ms, because jupyter-vuetify's core-js turned off the fast path.
Polyfills: the babel output is byte-identical before and after, because the lockfile change touches only core-js.
No core-js module from the old bundle is missing in the new one.
In Chromium 133, no native method is replaced.
In a real Solara page, an ipyvuetify
Btnand aTextFieldwithv_modelwork with the fixed bundles, without console errors.On this branch (local run on macOS with node 26; CI now uses node 22):
python -m buildandnpm pack, as in CI.The scan finds core-js 3.50.0 in 5 of 14 bundles and no core-js in the other 9, and exits 0.
On the stock 1.11.3
nodeps.js, it reports core-js 3.0.1 and exits 1.python -m buildandnpm packagain with node 22.23.3, in a fresh clone of this branch: both pass, and the scan again finds core-js 3.50.0 in 5 of 14 bundles and exits 0.With node 16, the CI run before the Node fix failed at
jupyter labextension buildwith "requires Node.js ^20.19.0 || >=22.12.0 (found v16.20.2)".KeyError: TraitNotAvailable). With"ipyvue>=1.7,<2"(1.12.0) it exits 0, andcomponents.pydoes not change.tests/ui/button_test.pywith the Solara runner (solara 1.64.0, ipyvue 1.x with the core-js fix, ipywidgets 8.1.9): passed.Its button screenshot looks the same as with stock 1.11.3 (largest channel difference 2 of 255).
Gaps
.readthedocs.yamlasks forbuild.os: ubuntu-20.04, which Read the Docs no longer accepts.This PR does not change that file, and 1.x has the same file, so a docs build of 1.x fails the same way.
The same file also asks for Node 16, so after an OS fix the docs install would probably hit the Node error above. Nobody tested that.
js/postcss.config.jsfor the build only, because the check foripyvuetify/js/lib/styles.cssdepends on the folder name. The CI checkout has the right folder name, so CI needs no patch.Release note
Vue 2 pages in Chrome and Edge no longer get slow regex work after jupyter-vuetify loads. Upgrade both packages:
🤖 Generated with Claude Code